#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

from common.logger import Logger
from common.util.cmd_utils import cmd_format
from informix.comm.common_cmd import CommonCommand
from informix.comm.const import InformixBaseCommand, InformixPath, GbaseCommand
from informix.comm.const import InformixExportCmdConstant, InformixCustomParmConstant, InformixInfo, GbaseInfo, \
    GbaseExportCmdConstant

log = Logger().get_logger("informix.log")


class InformixCommand:
    """
    本类可扩展完成所有命令的拼接, Informix 功能实现公共命令
    """

    def __init__(self, custom_dict):
        self.db_user = InformixInfo.INFORMIX_USER
        self._base_cmd = "su - " + InformixInfo.INFORMIX_USER + " -c {}"
        self.instance_name = custom_dict.get(InformixCustomParmConstant.INSTANCE_NAME, "")
        self.sqlhosts_path = custom_dict.get(InformixCustomParmConstant.SQLHOSTS_PATH, "")
        self.onconfig_path = custom_dict.get(InformixCustomParmConstant.CONFIG_PATH, "")
        self.cmd_constant = InformixExportCmdConstant
        self.sql_host = self.cmd_constant.INFORMIX_SQLHOSTS
        self.export_server_parameter = self.cmd_constant.INFORMIX_SERVER
        self._identify_env()
        self.export_cmd_resource = self._get_export_cmd("resource")
        self.export_cmd_backup = self._get_export_cmd("backup")

    @staticmethod
    def _format_export_cmd(export_type: str, export_text: str):
        return cmd_format('export {}={}', export_type, export_text)

    @staticmethod
    def _connect_cmd(cmd_list):
        return InformixBaseCommand.COMMAND_CONNECTION.join(cmd_list)

    def add_backup_file_device(self, bar_ixbar_path):
        """
        设置备份的文件设备
        :param bar_ixbar_path: BAR_IXBAR_PATH 环境变量
        :return: ret, res_cont
        """
        log.info(f"Enter add_backup_file_device method, bar_ixbar_path: {bar_ixbar_path}.")
        set_bar_bsalib_path_env_cmd = cmd_format(InformixBaseCommand.SET_BAR_BSALIB_PATH_ENV,
                                                 InformixPath.LIB_XBSA_PATH)
        cmd = cmd_format(self._base_cmd, self._connect_cmd([self.export_cmd_backup, set_bar_bsalib_path_env_cmd]))
        log.info(f"set_backup_file_device command: {cmd}")
        ret, res = CommonCommand.informix_execute_cmd(cmd)
        if not ret:
            log.error(f"Failed to exec command: {cmd}, res:{res}")
            return False
        return True

    def open_log_auto_backup(self, log_backup_tool_path):
        log.info("Enter open_log_auto_backup method.")
        set_alarmprogram_cmd = cmd_format(InformixBaseCommand.SET_ALARMPROGRAM_ENV, log_backup_tool_path)
        cmd = cmd_format(self._base_cmd, self._connect_cmd([self.export_cmd_backup, set_alarmprogram_cmd]))
        ret, res = CommonCommand.informix_execute_cmd(cmd)
        if not ret:
            log.error(f"Failed to exec command: {cmd}, res:{res}")
            return False
        return True

    def close_log_auto_backup(self):
        log.info("Enter open_log_auto_backup method.")
        set_alarmprogram_cmd = cmd_format(InformixBaseCommand.SET_ALARMPROGRAM_ENV, '')
        cmd = cmd_format(self._base_cmd, self._connect_cmd([self.export_cmd_backup, set_alarmprogram_cmd]))
        ret, res = CommonCommand.informix_execute_cmd(cmd)
        if not ret:
            log.error(f"Failed to exec command: {cmd}, res:{res}")
            return False
        return True

    def backup(self, backup_type, log_backup_staus, file_path):
        """
        执行备份任务
        :param file_path:
        :param log_backup_staus:
        :param backup_type: 0  1  2
        :return: ret, res_cont
        """
        log.info("Enter backup method.")
        backup = cmd_format(InformixBaseCommand.BACKUP_WITH_LOG, backup_type, file_path)
        if log_backup_staus:
            backup = cmd_format(InformixBaseCommand.BACKUP, backup_type, file_path)
        cmd = cmd_format(self._base_cmd, self._connect_cmd([self.export_cmd_backup, backup]))
        log.info(f"backup command: {cmd}")
        return CommonCommand.informix_execute_cmd(cmd)

    def show_status_and_version(self):
        """
        查询当前实例的状态或查询当前数据库是否安装，执行之后的逻辑需要在调用本方法的地方进行处理
        :return: ret, res_cont
        """
        log.info("Enter show_status_and_version method.")
        if self.db_user == InformixInfo.INFORMIX_USER:
            cmd = cmd_format(self._base_cmd, self._connect_cmd([self.export_cmd_resource,
                                                                InformixBaseCommand.QUERY_STATUS]))
            log.info(f"show_status_and_version method cmd:{cmd}")
        else:
            cmd = cmd_format(self._base_cmd, self._connect_cmd([self.export_cmd_resource,
                                                                GbaseCommand.QUERY_STATUS,
                                                                GbaseCommand.QUERY_VERSION]))
            log.info(f"show_status_and_version method cmd:{cmd}")
        return CommonCommand.informix_execute_cmd(cmd)

    def get_bound_node_instance_name(self):
        """
        查询当前集群绑定的节点实例名
        :return: ret, res_cont
        """
        log.info("Enter get_bound_node_instance_name method.")
        cmd = cmd_format(self._base_cmd, self._connect_cmd([
            self.export_cmd_resource, InformixBaseCommand.QUERY_CLUSTER_BOUND_NODE]))
        return CommonCommand.informix_execute_cmd(cmd)

    def get_enter_sql_cmd(self):
        return self._base_cmd

    def _parse_onconfig_file_name(self):
        element_list = self.onconfig_path.split("/")
        return element_list[len(element_list) - 1]

    def _get_export_cmd(self, types):
        onconfig_name = self._parse_onconfig_file_name()
        export_informix_server_cmd = self._format_export_cmd(self.export_server_parameter, self.instance_name)
        export_onconfig = self._format_export_cmd(self.cmd_constant.ONCONFIG, onconfig_name) \
            if types == "resource" else self._format_export_cmd(self.cmd_constant.ONCONFIG, onconfig_name)
        export_sqlhost = self._format_export_cmd(self.sql_host, self.sqlhosts_path)
        return self._connect_cmd([export_informix_server_cmd, export_onconfig, export_sqlhost])

    def _identify_env(self):
        """
        执行指令前确认环境类型，通过查找进程中的用户鉴别 informix 和 GBase8s
        :return: ret
        """
        log.info("Start to identify the environment type")
        cmd = "su - informix -c 'echo 0'"
        ret, res_cont = CommonCommand.informix_execute_cmd(cmd)
        if not ret:
            log.info("This is a GBase8s environment")
            self.db_user = GbaseInfo.GBASE_USER
            self._base_cmd = "su - " + self.db_user + " -c {}"
            self.cmd_constant = GbaseExportCmdConstant
            self.export_server_parameter = self.cmd_constant.GBASE_SERVER
            self.sql_host = self.cmd_constant.GBASE_SQLHOSTS
        else:
            log.info("This is a informix environment")
